import logging

import cv2
import numpy as np
import yaml


def send_alert(arg1, arg2):
    logging.info(f"get frame and detection_info: {arg2}, Alert sent")


def get_args(section):
    with open("config.yml", "r") as f:
        config = yaml.safe_load(f)
    return config[section]


def letterbox(
    img,
    new_shape=(640, 640),
    color=(114, 114, 114),
    auto=False,
    scaleFill=False,
    scaleup=True,
):
    shape = img.shape[:2]  # current shape [height, width]
    if isinstance(new_shape, int):
        new_shape = (new_shape, new_shape)

    # Scale ratio (new / old)
    r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
    if not scaleup:  # only scale down, do not scale up (for better test mAP)
        r = min(r, 1.0)

    # Compute padding
    ratio = r, r  # width, height ratios
    new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
    dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh padding
    if auto:  # minimum rectangle
        dw, dh = np.mod(dw, 64), np.mod(dh, 64)  # wh padding
    elif scaleFill:  # stretch
        dw, dh = 0.0, 0.0
        new_unpad = (new_shape[1], new_shape[0])
        ratio = new_shape[1] / shape[1], new_shape[0] / shape[0]  # width, height ratios

    dw /= 2  # divide padding into 2 sides
    dh /= 2

    if shape[::-1] != new_unpad:  # resize
        img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR)
    top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
    left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
    img = cv2.copyMakeBorder(
        img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color
    )  # add border
    return img, ratio, (dw, dh)


def xyxy2xywh(x):
    # convert nx4 boxes from [x1, y1, x2, y2] to [x, y, w, h]
    # where xy1=top-left, xy2=botttom-right
    y = np.copy(x)
    y[:, 0] = (x[:, 0] + x[:, 2]) / 2  # x center
    y[:, 1] = (x[:, 1] + x[:, 3]) / 2  # y center
    y[:, 2] = x[:, 2] - x[:, 0]  # width
    y[:, 3] = x[:, 3] - x[:, 1]  # height
    return y


def xywh2xyxy(x):
    y = np.zeros_like(x)
    y[:, 0] = x[:, 0] - x[:, 2] / 2  # top left x
    y[:, 1] = x[:, 1] - x[:, 3] / 2  # top left y
    y[:, 2] = x[:, 0] + x[:, 2] / 2  # bottom right x
    y[:, 3] = x[:, 1] + x[:, 3] / 2  # bottom right y
    return y


def clip_coords(boxes, shape):
    boxes[:, [0, 2]] = boxes[:, [0, 2]].clip(0, shape[1])  # x1, x2
    boxes[:, [1, 3]] = boxes[:, [1, 3]].clip(0, shape[0])  # y1, y2


def get_color(idx):
    idx = idx * 3
    color = ((37 * idx) % 255, (17 * idx) % 255, (29 * idx) % 255)

    return color


def plot_tracking(image, tlwhs):
    img = np.ascontiguousarray(np.copy(image))
    line_thickness = 3
    for i, tlwh in enumerate(tlwhs):

        x1, y1, w, h = tlwh
        intbox = tuple(map(int, (x1, y1, x1 + w, y1 + h)))
        color = get_color(i)
        cv2.rectangle(
            img, intbox[0:2], intbox[2:4], color=color, thickness=line_thickness
        )
    return img


def get_person(frame, tlwh, padding=25):
    x1, y1, w, h = tlwh
    x1 = x1 - padding if x1 - padding >= 0 else 0
    x2 = x1 + w + padding if (x1 + w + padding) < frame.shape[1] else frame.shape[1]
    y1 = y1 - padding if y1 - padding >= 0 else 0
    y2 = y1 + h + padding if (y1 + h + padding) < frame.shape[0] else frame.shape[0]
    xyxy = np.array([x1, y1, x2, y2]).reshape(1, -1)
    b = xyxy2xywh(xyxy)
    xyxy = xywh2xyxy(b)
    clip_coords(xyxy, frame.shape)
    crop = frame[int(xyxy[0, 1]) : int(xyxy[0, 3]), int(xyxy[0, 0]) : int(xyxy[0, 2])]
    return crop[..., ::-1]


def get_detect_info(client):
    detection_info = {}
    res = True
    detection_info["strem_name"] = client.get("stream_name")
    detection_info["type"] = client.get("type")
    detection_info["url"] = client.get("url")
    detection_info["time_threshold"] = client.get("time_threshold")
    detection_info["error_threshold"] = client.get("error_threshold")
    for key in detection_info.keys():
        if detection_info[key] is None:
            res = False
            break
    return res, detection_info
